| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899 |
- 'use client';
- import './style.scss';
- import 'animate.css';
- import { use, useEffect, useState } from 'react';
- import { useDonationAlert } from '@/hooks/useDonationAlert';
- import { DonationAlertConfig } from '@/types/donation';
- import { fetchApi } from '@/lib/utils/client';
- import View from './view';
- type Props = {
- params: Promise<{ widgetToken: string }>;
- };
- const DEFAULT_CONFIG: DonationAlertConfig = {
- id: 0,
- title: '',
- amount: 0,
- matchType: 0,
- message: '{이름}님이 {금액}을 후원해주셨습니다!',
- playDelaySec: 0,
- displayDurationSec: 10,
- popupEffect: 'fadeIn',
- textEffect: null,
- nicknameFontFamily: null,
- nicknameFontSize: 24,
- nicknameFontColor: '#FFD700',
- amountFontFamily: null,
- amountFontSize: 24,
- amountFontColor: '#FF6B35',
- messageFontFamily: null,
- messageFontSize: 18,
- messageFontColor: '#FFFFFF',
- templateFontFamily: null,
- templateFontSize: 24,
- templateFontColor: '#FFFFFF',
- enableImage: true,
- imageUrl: '/resources/donate-default-image.gif',
- enableSound: true,
- soundUrl: '/sounds/default-donate-effect.mp3',
- isActive: true
- };
- function matchConfig(configs: DonationAlertConfig[], amount: number): DonationAlertConfig
- {
- // 1순위: Exact 매칭 (MatchType === 1)
- const exact = configs.find(c => c.matchType === 1 && c.amount === amount && c.isActive);
- if (exact) {
- return exact;
- }
- // 2순위: MinThreshold (MatchType === 0) — 금액 이상 중 가장 높은 것
- const thresholds = configs
- .filter(c => c.matchType === 0 && c.amount <= amount && c.isActive)
- .sort((a, b) => b.amount - a.amount);
- return thresholds[0] ?? DEFAULT_CONFIG;
- }
- export default function AlertPage({ params }: Props)
- {
- const { widgetToken } = use(params);
- const hubUrl = process.env.NEXT_PUBLIC_API_URL + '/hubs/donation';
- const [configs, setConfigs] = useState<DonationAlertConfig[]>([]);
- const { current, remoteState, onAlertComplete } = useDonationAlert(
- widgetToken,
- hubUrl,
- // 위젯이 실제 재생할 displayDurationSec 을 리모콘 타이머용으로 hub 에 동봉
- (alert) => matchConfig(configs, alert.amount).displayDurationSec
- );
- // API에서 config 목록 로드
- useEffect(() => {
- fetchApi<{ list: DonationAlertConfig[] }>(`/api/widget/alert/config/${widgetToken}`, { silent: true }).then(res => {
- if (res.success && res.data?.list) {
- setConfigs(res.data.list);
- }
- }).catch(() => {});
- }, [widgetToken]);
- const config = current ? matchConfig(configs, current.amount) : null;
- return (
- <div className="alert-page">
- {current && config && (
- <View
- key={current.alertID}
- alert={current}
- config={config}
- isAudioOnly={remoteState.isAudioOnly}
- isVideoOnly={remoteState.isVideoOnly}
- onComplete={onAlertComplete}
- />
- )}
- </div>
- );
- }
|